#include <mutex>
#include <atomic>
#include <iostream>

// C++11 之后的实现
// 加入 atomic
class Singleton {
public:
    static Singleton* getInstance();

private:
    static std::mutex m_mutex;
    static std::atomic<Singleton*> m_instance;

private:
    Singleton() = default;

    Singleton(const Singleton& ) = delete;
    Singleton(Singleton&& ) = delete;

    Singleton& operator=(const Singleton& ) = delete;
    Singleton& operator=(Singleton&& ) = delete;
};

std::mutex Singleton::m_mutex;
std::atomic<Singleton*> Singleton::m_instance;

// 直接用 atomic::load(std::memory_order_acquire)
//
// Singleton* Singleton::getInstance() {
//     Singleton* tmp = m_instance.load(std::memory_order_acquire);
//     if (tmp == nullptr) {
//         std::lock_guard<std::mutex> lock(m_mutex);
//         tmp = m_instance.load(std::memory_order_relaxed);
//         if (tmp == nullptr) {
//             tmp = new Singleton();
//             m_instance.store(tmp, std::memory_order_release);
//         }
//     }
//     return tmp;
// }

// 完美线程安全版
Singleton* Singleton::getInstance() {
    Singleton* tmp = m_instance.load(std::memory_order_relaxed);
    std::atomic_thread_fence(std::memory_order_acquire); // 获取内存 fence, 防止fence后的内存操作重排到fence前的(任意)load之前
    if (tmp == nullptr) {
        std::lock_guard<std::mutex> lock(m_mutex);
        tmp = m_instance.load(std::memory_order_relaxed);
        if (tmp == nullptr) {
            tmp = new Singleton();
            std::atomic_thread_fence(std::memory_order_release); // 防止fence之前的内存操作重排到后面的 store 之后
            m_instance.store(tmp, std::memory_order_relaxed);
        }
    }
    return tmp;
}

int main() {
    Singleton* instance = Singleton::getInstance();
    std::cout << instance << std::endl;
    Singleton *instance2 = Singleton::getInstance();
    std::cout << instance2 << std::endl;

    delete instance;

    return 0;
}